package com.cnctema.easecalendar_weekly_view.utils

import com.cnctema.easecalendar_weekly_view.database.EventWeeklyView
import java.util.ArrayList

/**
 * @Title: Constants
 * @Description: 周视图日程方块计算工具类
 * @Author: cnctema
 * @CreateDate: 2020/7/24 22:45
 */
object EventWeeklyViewUtils {

    //日历方格排布算法
    fun eventViewArrangement(evList:ArrayList<EventWeeklyView>?):ArrayList<EventWeeklyView>? {
        if (evList == null || evList.size < 1){
            return null
        }else if (evList.size==1){
            return evList
        }

        evList.sortBy { it.stTime }     //根据开始时间进行排序

        val hashMap = HashMap<Int, ArrayList<EventWeeklyView>>()
        val maxColDenom = actGreedyArg(evList,hashMap)
        return exEvArray(hashMap,maxColDenom)

    }

    //活动贪婪算法
    private fun actGreedyArg(evList: ArrayList<EventWeeklyView>,
                             hashMap:HashMap<Int,ArrayList<EventWeeklyView>>):Int{
        var oriIndex = 0    //列标号

        var countNum = 0     //已标记数
        var maxColDenom = 0 //最大列数

        var pre = 0     //前指针
        var sPre = 0    //预前指针
        var isfindPre = false   //是否找到下一个预前指针
        while (countNum<evList.size){
            countNum++
            maxColDenom++

            //查找对比对象
            for (i in sPre until evList.size){
                if (!evList[sPre].sign){
                    pre = sPre
                    evList[pre].sign = true
                    isfindPre = false

                    if (!hashMap.containsKey(oriIndex)){
                        hashMap[oriIndex] = ArrayList<EventWeeklyView>()
                    }
                    hashMap[oriIndex]?.add(evList[pre])   //添加第一个元素

                    break
                }
            }
            //逐个对比后续的对象
            var index = oriIndex
            for(next in pre until evList.size){
                val preEv = evList[pre]
                val nextEv = evList[next]

                if (nextEv.sign){
                    continue
                }

                if (nextEv.stTime>=preEv.edTime){
                    nextEv.colIndex = oriIndex
                    nextEv.sign = true

                    //添加到哈希表
                    hashMap[oriIndex]?.add(nextEv)

                    pre = next          //移动前指针
                    countNum++          //标记计数+1
                    index = oriIndex    //复位标志符
                }else{
                    if (!isfindPre){    //找到预前指针
                        sPre = next     //设置预前指针
                        isfindPre = true
                    }

                    index++
                    nextEv.colIndex = index
                }
            }
            oriIndex++
        }
        return maxColDenom
    }

    private fun exEvArray(hashMap:HashMap<Int,ArrayList<EventWeeklyView>>,
                          maxColDenom:Int):ArrayList<EventWeeklyView> {
        val outputList = ArrayList<EventWeeklyView>()

        //遍历除最后一列的每一列
        for (preIndex in 0 until (maxColDenom-1)){
            //遍历其中一列里的事件方格
            val preArray = hashMap[preIndex]?:continue
            for (ev in preArray){
                ev.colDenom = maxColDenom
                var colNum = maxColDenom-ev.colIndex

                //遍历后面的每一列
                for (nextIndex in (preIndex+1) until maxColDenom){
                    var isFound = false
                    //遍历后面其中一列里的事件方格
                    val nextArray = hashMap[nextIndex]?:continue
                    for (ev2 in nextArray){
                        if (ev.isTouch(ev2.stTime,ev2.edTime)){
                            colNum = nextIndex-ev.colIndex
                            isFound = true
                            break
                        }
                    }
                    if (isFound){
                        break
                    }
                }
                ev.colNum = colNum
                outputList.add(ev)
            }
        }
        hashMap[maxColDenom-1]?.forEach {ev->
            ev.colDenom = maxColDenom
            ev.colNum = 1
            outputList.add(ev)
        }
        return outputList
    }

}